/*
Ryan Perry
April 25, 2008
*/

#include "DrawableObj.h"


/* Setting up our object.  currentFrame is assigned to -1 to ensure that the
    first frame will play, the first time we access our frame vector.  We also
    make sure our currentFrameDuration and currentFrameVectorSize are set to
    zero to avoid comparison difficulties. By default, our frameVector will point
    to our intro animation and is set to loop. */
DrawableObj::DrawableObj()
{
    currentFrame = -1;
    currentFrameDuration = 0;
    currentFrameVectorSize = 0;
    frameVector = &introVector;
    loopAnimation = true;
}

/* Sets the X (horizontal) position of our object.  Nothing special. */
void DrawableObj::setX(int givenX)
{
    objectX = givenX;
}

/* Same as above, only with Y. (vertical) */
void DrawableObj::setY(int givenY)
{
    objectY = givenY;
}

/* Returns our horizontal coordinate. */
unsigned int DrawableObj::getX()
{
    return objectX;
}

/* Just like the previous method, except returns a vertical coordinate. */
unsigned int DrawableObj::getY()
{
    return objectY;
}

/* This is where it starts to get a little more involved.  We setup a temporary
    unsigned integer to hold the index position of the newly created vector item.
    We also create a FrameContainer vector pointer to point to the animation vector
    that was specified.  We then use that targetVector pointer to point to our
    vector's pointer to a frame container.  Pointer.  This is done to assign surface
    and duration values. */
void DrawableObj::addFrames(int specificAnimation, std::string fileName, int duration)
{
    unsigned int lastElement;
    std::vector<FrameContainer*>* targetVector;
    if (specificAnimation == 1)
        targetVector = &idleVector;
    else
        targetVector = &introVector;
    targetVector->push_back(new FrameContainer);
    lastElement = (targetVector->size() - 1);
    targetVector->at(lastElement)->surface = IMG_Load(fileName.c_str());
    targetVector->at(lastElement)->duration = duration;
}

/* We set our current frame here.  As long as it's less than the size
    of our vector, (since it's basically an index for the vector) we
    allow the value.*/
void DrawableObj::setFrame(unsigned int specifiedFrame)
{
    if (specifiedFrame < frameVector->size())
        currentFrame = specifiedFrame;
}

/* What frameVector points to is changed here.  As it stands, there's only
    two animation sets.  One is idle animation and one is the intro animation.
    1 = idle, 0 (or anything else) = intro.  After changing the vector pointer
    we also update the frame currentFrameVectorSize and currentFrameDuration
    to zero so as to avoid conflicts in animating. */
void DrawableObj::setAnimation(unsigned int specificAnimation)
{
    if (specificAnimation == 1)
        frameVector = &idleVector;
    else
        frameVector = &introVector;
    currentFrame = -1;
    currentFrameVectorSize = frameVector->size();
    currentFrameDuration = 0;
}

/* Returns the number of the current frame, zero to whatever.  This is the number
    used as the vector index. */
int DrawableObj::getFrame()
{
    return currentFrame;
}

/* Do you want the animation to loop?  If so, pass this a boolean true.
    If false, the animation will not reset the index and the last frame
    continues to be displayed. */
void DrawableObj::setDoLoop(bool yayORnay)
{
    loopAnimation = yayORnay;
}

/* We have two methods that interact with Graphics::draw.  One is this one.  The
    only difference between this and the next is that this one will only return
    the current frame.  No other processing is done. */
SDL_Surface* DrawableObj::getCurrentFrameStatic()
{
    if (currentFrame == -1)
        currentFrame = 0;
    return frameVector->at(currentFrame)->surface;
}

/* This is the more interesting of the "get frame" methods.  In this one, the current
    SDL surface is returned...but we also advance the currentFrame (if it's time), do a
    check to make sure it's kosher, and fix things in the event they are not, indeed,
    kosher. The currentFrame is reset to the beginning of the array, unless we've specified
    loopAnimation to be false. */
SDL_Surface* DrawableObj::getCurrentFrame()
{
    if (SDL_GetTicks() > currentFrameDuration)
    {
        currentFrame++;
        if (currentFrame > (currentFrameVectorSize - 1))
        {
            if (loopAnimation)
                currentFrame = 0;
            else
                currentFrame--;
        }
        currentFrameDuration = (SDL_GetTicks() + (frameVector->at(currentFrame)->duration * 10));
    }
    if (currentFrame == -1)
        currentFrame = 0;
    return frameVector->at(currentFrame)->surface;
}

/* Our constructor is pretty long-winded.  All it's doing is clearing out our vectors
    and deleting the SDL_Surface objects that we've dynamically created.  Ultimately,
    this will be narrowed down by using a vector cleaning method that can be used for
    each of our vectors, without code redundancy. */
DrawableObj::~DrawableObj()
{
    while (!introVector.empty())
      {
          SDL_FreeSurface(introVector.at(0)->surface);
          delete introVector.at(0);
          introVector.erase(introVector.begin());
      }
      introVector.clear();

      while (!idleVector.empty())
      {
          SDL_FreeSurface(idleVector.at(0)->surface);
          delete idleVector.at(0);
          idleVector.erase(idleVector.begin());
      }
      idleVector.clear();
}
